package com.hengx.cellview.cell;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;

import android.util.StateSet;
import android.view.MotionEvent;
import android.view.View;
import com.hengx.cellview.CellView;
import java.util.ArrayList;
import java.util.List;

public class DrawableCell extends Cell {

    private Drawable mDrawable;
    private List<Object> clips;
    private CellView view;
    
    public DrawableCell() {
        this(null);
    }
    public DrawableCell(Drawable drawable) {
        this.mDrawable = drawable;
        this.clips = new ArrayList<>();
    }
    
    @Override
    public void init(CellView view) {
        super.init(view);
        this.view = view;
        this.clips.add(getBounds());
        updateDrawable(mDrawable);
    }
    
    @Override
    public void draw(Paint paint, Canvas canvas, float scaleFactor) {
        int len = 0;
        for(int i = 0; i < clips.size(); i++) {
            Object clip = clips.get(i);
            canvas.save();
            if (clip instanceof RectF) {
                canvas.clipRect((RectF) clip);
            } else if (clip instanceof Rect) {
                canvas.clipRect((Rect) clip);
            } else if (clip instanceof Path) {
                canvas.clipPath((Path) clip);
            } else {
                canvas.restore();
                continue;
            }
            len++;
        }
        if (mDrawable != null) {
            mDrawable.draw(canvas);
        }
        while(len > 0) {
            canvas.restore();
            len--;
        }
    }
    
    @Override
    public void setBounds(float x, float y, float endX, float endY) {
        super.setBounds(x, y, endX, endY);
        if (mDrawable != null) {
            mDrawable.setBounds(Math.round(x), Math.round(y), Math.round(endX), Math.round(endY));
        }
    }
    

    public Drawable getDrawable() {
        return this.mDrawable;
    }

    public void setDrawable(Drawable drawable) {
        if (drawable == mDrawable) return;
        if (view != null) updateDrawable(drawable);
    }
    
    public void addClip(Rect rect) {
    	this.clips.add(rect);
    }
    
    public void addClip(RectF rect) {
    	this.clips.add(rect);
    }
    
    public void addClip(Path path) {
    	this.clips.add(path);
    }
    
    public void removeClip(int index) {
    	this.clips.remove(index);
    }
    
    public Object getClip(int index) {
    	return this.clips.get(index);
    }
    
    public int getClipCount() {
    	return this.clips.size();
    }
    
    public int indexOfClip(Object clip) {
    	return this.clips.indexOf(clip);
    }
    
    public void clearClip() {
    	this.clips.clear();
    }
    
    @Override
    public boolean onTouch(CellView view, MotionEvent event) {
        if (mDrawable == null || !mDrawable.isStateful()) {
            return super.onTouch(view, event);
        }
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            mDrawable.setState(getState(view.getWindowVisibility() == View.VISIBLE, true));
            mDrawable.setHotspot(event.getX(), event.getY());
            break;
        case MotionEvent.ACTION_MOVE:
            mDrawable.setHotspot(event.getX(), event.getY());
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            mDrawable.setHotspot(event.getX(), event.getY());
            mDrawable.setState(getState(view.getWindowVisibility() == View.VISIBLE, false));
            break;
        }
        return super.onTouch(view, event);
    }
    
    private void updateDrawable(Drawable d) {
        if (view == null) return;
    	boolean sameDrawable = false;
        if (mDrawable != null) {
            sameDrawable = mDrawable == d;
            mDrawable.setCallback(null);
            view.unscheduleDrawable(mDrawable);
            if (!sameDrawable && view.isAttachedToWindow()) {
                mDrawable.setVisible(false, false);
            }
        }
        mDrawable = d;
        if (d != null) {
            d.setCallback(new Drawable.Callback() {
                @Override
                public void invalidateDrawable(Drawable arg0) {
                    view.postInvalidate();
                }
                @Override
                public void unscheduleDrawable(Drawable arg0, Runnable arg1) {
                    view.removeCallbacks(arg1);
                }
                @Override
                public void scheduleDrawable(Drawable arg0, Runnable arg1, long arg2) {
                    view.postDelayed(arg1, arg2);
                }
                
            });
            //d.setLayoutDirection(view.getLayoutDirection());
            if (d.isStateful()) {
                d.setState(getState(view.getWindowVisibility() == View.VISIBLE, false));
            }
            if (!sameDrawable) {
                boolean visible = view.isAttachedToWindow() && view.getWindowVisibility() == View.VISIBLE && view.isShown();
                d.setVisible(visible, true);
            }
            RectF rect = getBounds();
            d.setBounds(Math.round(rect.left), Math.round(rect.top), Math.round(rect.right), Math.round(rect.bottom));
            /*mDrawableWidth = d.getIntrinsicWidth();
            mDrawableHeight = d.getIntrinsicHeight();
            applyImageTint();
            applyColorFilter();
            applyAlpha();
            applyXfermode();
            configureBounds();*/
        }/* else {
            mDrawableWidth = mDrawableHeight = -1;
        }*/
    }
    
    
    private int[] getState(boolean window_focused, boolean pressed) {
    	if (window_focused && pressed) {
            return new int[] {android.R.attr.state_window_focused, android.R.attr.state_pressed, android.R.attr.state_enabled, android.R.attr.state_multiline};
        } else if (window_focused) {
            return new int[] {android.R.attr.state_window_focused, android.R.attr.state_enabled, android.R.attr.state_multiline};
        } else if (pressed) {
            return new int[] {android.R.attr.state_pressed, android.R.attr.state_enabled, android.R.attr.state_multiline};
        } else {
            return new int[] {android.R.attr.state_enabled, android.R.attr.state_multiline};
        }
    }
    
}
